# coding=utf-8
import re
import urllib
import urllib2
from urlparse import parse_qs
import datetime
from flask import session
from uzwan import config
from uzwan.lib import uuid

class OAuthError(StandardError):
    def __init__(self, error):
        self.error = error
        StandardError.__init__(self, error)

    def __str__(self):
        return 'QQAuth Error: %s' % self.error

class QQOAuth(object):
    openid_repr = re.compile(r'"openid"\s*:"(\w+)"')

    def __init__(self):
        qq_oauth_config = config.CONNECTS['qq']
        self.authorize_url = qq_oauth_config['authorize_url']
        self.request_token_url = qq_oauth_config['request_token_url']
        self.openid_url = qq_oauth_config['openid_url']
        self.scope = qq_oauth_config['scope']
        self.appid = qq_oauth_config['appid']
        self.secret = qq_oauth_config['secret']
        self.authorize_callback = qq_oauth_config['authorize_callback']

    def get_authorize_url(self):
        state = uuid()
        param = {'client_id': self.appid, 'redirect_uri': self.authorize_callback, 'response_type': 'code', 'state': state}
        session['qq.oauth.state'] = state
        return '%s?%s' % (self.authorize_url, urllib.urlencode(param))

    def get_access_token(self, code, state):
        if session.pop('qq.oauth.state') != state:
            raise OAuthError('Acquire qq oauth access_token failed, caused by csrf:state value confilict')

        param = {'client_id': self.appid, 'client_secret': self.secret, 'grant_type': 'authorization_code', 'code': code, 'redirect_uri': self.authorize_callback}
        try:
            req = urllib2.Request(self.request_token_url, urllib.urlencode(param))
            resp = urllib2.urlopen(req)
        except urllib2.URLError, e:
            raise OAuthError('Acquire qq oauth access_token failed, caused by: %s' % str(e))
        try:
            resp_content = resp.read()
            resp_data = parse_qs(resp_content)
            return (resp_data['access_token'][0], datetime.datetime.now() + datetime.timedelta(seconds=int(resp_data['expires_in'][0])))
        except StandardError, e:
            raise OAuthError('Acquire qq oauth access_token failed, caused by parse content:%s error:%s' % (resp_content, str(e)))

    def get_openid(self, access_token):
        param = {'access_token': access_token}
        try:
            req = urllib2.Request(self.openid_url, urllib.urlencode(param))
            resp = urllib2.urlopen(req)
        except urllib2.URLError, e:
            raise OAuthError('Acquire qq open id failed, caused by: %s' % str(e))
        try:
            resp_content = resp.read()
            openid_matcher = self.openid_repr.search(resp_content)
            return openid_matcher.group(1)
        except StandardError, e:
            raise OAuthError('Acquire qq open id failed, caused by parse content:%s error:%s' % (resp_content, str(e)))


